const fs = require("fs");
const path = require("path");

import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import babel from "@rollup/plugin-babel";
import glslify from "rollup-plugin-glslify";
import { terser } from "rollup-plugin-terser";
import replace from "@rollup/plugin-replace";

const camelCase = require("camelcase");

const { NODE_ENV } = process.env;

const pkgsRoot = path.join(__dirname, "packages");
const loadersRoot = path.join(__dirname, "loaders");
const test = path.join(__dirname, "test");

const pkgs = fs
  .readdirSync(pkgsRoot)
  .filter((val) => {
    if (val.includes(".")) {
      return false;
    }
    return true;
  })
  .map((dir) => path.join(pkgsRoot, dir))
  .map((location) => {
    return {
      location: location,
      pkgJson: require(path.resolve(location, "package.json"))
    };
  });

const loaderPkgs = fs
  .readdirSync(loadersRoot)
  .filter((val) => {
    if (val.includes(".")) {
      return false;
    }
    return true;
  })
  .map((dir) => path.join(loadersRoot, dir))
  .map((location) => {
    return {
      location: location,
      pkgJson: require(path.resolve(location, "package.json"))
    };
  });

function toGlobalName(pkgName) {
  return camelCase(pkgName);
}

const extensions = [".js", ".jsx", ".ts", ".tsx"];

const commonPlugins = [
  resolve({ extensions, preferBuiltins: true }),
  glslify({
    include: [/\.glsl$/]
  }),
  babel({
    extensions,
    babelHelpers: "bundled",
    // exclude: ["node_modules/**", "loaders/**/node_modules/**", "packages/**/node_modules/**", "test/node_modules/**", "main/node_modules/**"]
    exclude: [
      "node_modules/**",
      "loaders/**/node_modules/**",
      "packages/**/node_modules/**",
      "test/node_modules/**",
      "main/node_modules/**"
    ]
  }),
  commonjs()
];

function config({ location, pkgJson }) {
  const input = path.join(location, "src", "index.ts");
  const external = Object.keys(pkgJson.dependencies || {});
  const name = pkgJson.name;
  commonPlugins.push(
    replace({
      __buildVersion: pkgJson.version
    })
  );

  return {
    umd: (compress) => {
      let file = path.join(location, "dist", "browser.js");
      const plugins = [...commonPlugins];
      if (compress) {
        plugins.push(terser());
        file = path.join(location, "dist", "browser.min.js");
      }

      const globalName = toGlobalName(pkgJson.name);

      const globals = {};
      external.forEach((pkgName) => {
        globals[pkgName] = toGlobalName(pkgName);
      });

      return {
        input,
        // external: name === "nirnava" ? {} : external,
        external: external,
        output: [
          {
            file,
            name: globalName,
            format: "umd",
            sourcemap: false, // true,
            globals
          }
        ],
        plugins
        //: name === "nirnava" ? [] : plugins
      };
    },
    module: () => {
      const plugins = [...commonPlugins];
      return {
        input,
        external,
        output: [
          {
            file: path.join(location, pkgJson.module),
            format: "es",
            sourcemap: true
          },
          {
            file: path.join(location, pkgJson.main),
            format: "commonjs"
          }
        ],
        plugins
      };
    }
  };
}

async function makeRollupConfig({ type, compress = true, visualizer = true, ..._ }) {
  return config({ ..._ })[type](compress, visualizer);
}

let promises = [];

switch (NODE_ENV) {
  case "UMD":
    promises.push(...getUMD());
    break;
  case "MODULE":
    promises.push(...getModule());
    break;
  case "ALL":
    promises.push(...getAll());
    break;
  default:
    break;
}

function getUMD() {
  const configs = [...pkgs, ...loaderPkgs].filter((pkg) => pkg.pkgJson.browser);
  const umds = configs
    .map((config) => makeRollupConfig({ ...config, type: "umd" }))
    .concat(
      configs.map((config) =>
        makeRollupConfig({
          ...config,
          type: "umd",
          compress: false,
          visualizer: false
        })
      )
    );
  return umds;
}

function getModule() {
  const configs = [...pkgs, ...loaderPkgs];
  return configs.map((config) => makeRollupConfig({ ...config, type: "module" }));
}

function getAll() {
  return [...getModule(), ...getUMD()];
}

export default Promise.all(promises);
